package org.example.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.example.config.exception.SocialLoginException;
import org.example.dao.entity.UserEntity;
import org.example.dao.entity.UserSocialEntity;
import org.example.service.UserService;
import org.example.utils.JwtUtil;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.view.RedirectView;

import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Tag(name = "用户模块")
@RestController
@RequiredArgsConstructor
public class UserController {
    private final UserService userService;

    private final StringRedisTemplate stringRedisTemplate;

    @Operation(summary = "用户注册")
    @PostMapping("/user/register")
    public void register(@RequestBody UserEntity userEntity) {
        userService.register(userEntity.getUsername(), userEntity.getPassword());
    }

    @Operation(summary = "用户登录（账号 + 密码）")
    @PostMapping("/user/login")
    public String login(@RequestBody UserEntity userEntity) {
        return userService.userLogin(userEntity.getUsername(), userEntity.getPassword());
    }

    @Operation(summary = "用户登录（令牌）")
    @GetMapping("/user/login/{token}")
    public String loginWithToken(@PathVariable("token") String token) {
        return userService.loginWithToken(token);
    }

    @Operation(summary = "社交登录")
    @GetMapping("/user/socialLogin")
    public RedirectView socialLogin() {
        // 生成 state
        String state = UUID.randomUUID().toString();
        stringRedisTemplate.opsForValue().set(state, "");

        RedirectView redirectView = new RedirectView();

        // TODO 后续需要扩展（当前demo测试）
        redirectView.setUrl("https://github.com/login/oauth/authorize?response_type=code&client_id=Ov23liCRrjIhQNshHlZq&scope=read:user%20user:email&state="+ state +"&redirect_uri=http://localhost:7575/login/oauth2/code/github");
        return redirectView;
    }

    @Operation(summary = "用 code 换取 access_token")
    @GetMapping("/login/oauth2/code/github")
    public String exchangeAccessToken(@RequestParam("code") String code, @RequestParam("state") String state) {
         if(stringRedisTemplate.opsForValue().get(state) == null) {
             throw new SocialLoginException("state字段为空！");
         }
         try {
            // 1. 准备请求参数
            MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
            String clientId = "Ov23liCRrjIhQNshHlZq";
            requestBody.add("client_id", clientId);
            String clientSecret = "22acc1775ea1eb691e9d2bc5ef062096ce66645e";
            requestBody.add("client_secret", clientSecret);
            requestBody.add("code", code);
            // 2. 设置请求头，要求返回 JSON 格式
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            headers.add("Accept", "application/json");

            // 3. 创建 HTTP 请求
            HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(requestBody, headers);

            // 4. 发送 POST 请求到 GitHub 令牌端点
            RestTemplate restTemplate = new RestTemplate();
            String GITHUB_TOKEN_URL = "https://github.com/login/oauth/access_token";
            ResponseEntity<String> response = restTemplate.exchange(
                    GITHUB_TOKEN_URL,
                    HttpMethod.POST,
                    request,
                    String.class
            );

            // 5. 解析响应获取 access_token
            if (response.getStatusCode() == HttpStatus.OK) {
                ObjectMapper mapper = new ObjectMapper();
                Map<String, Object> responseMap = mapper.readValue(response.getBody(), Map.class);

                String accessToken = (String) responseMap.get("access_token");
                if (accessToken != null) {
                    UserSocialEntity userInfo = userService.getUserInfo(accessToken);
                    String token = JwtUtil.generateToken(userInfo.getName());
                    stringRedisTemplate.opsForValue().set(userInfo.getName(), token, 30, TimeUnit.MINUTES);
                    return token;
                }
            }
            throw new SocialLoginException("获取 access_token 失败");
        } catch (Exception e) {
            e.printStackTrace();
            return "处理请求时发生错误";
        }
    }

    @Operation(summary = "用户注销")
    @GetMapping("/user/revoked")
    public String revoked() {
        return userService.revoked();
    }

    @Operation(summary = "退出登录")
    @GetMapping("/user/logout")
    public String logout() {
        return userService.logout();
    }
}
